#include "Value.h"

const Value Value::null = Value(NIL);
const Value Value::NaN = Value( std::numeric_limits<float>::quiet_NaN() );

TypeInfo::StringValueTypeMap TypeInfo::types = TypeInfo::StringValueTypeMap();
bool TypeInfo::init = false;

void TypeInfo::setup()
{
	/*
	#define TYPE_DECLARE(x,y) TypeInfo::types[#x] = y
	TYPE_DECLARE(null,NIL);
	TYPE_DECLARE(nil,NIL);
	TYPE_DECLARE(undefined,NIL);
	TYPE_DECLARE(0,NIL);

	TYPE_DECLARE(int,INT);
	TYPE_DECLARE(float,FLOAT);
	*/
	
	TypeInfo::types["null"] 	= NIL;
	TypeInfo::types["nil"]		= NIL;
	TypeInfo::types["undefined"] 	= NIL;
	TypeInfo::types["0"] 		= NIL;

	TypeInfo::types["bool"]		= BOOL;

	TypeInfo::types["int"]		= INT;

	TypeInfo::types["float"] 	= FLOAT;
	TypeInfo::types["number"]	= FLOAT;

	TypeInfo::types["string"] 	= STRING;

	TypeInfo::types["object"] 	= OBJECT;
	TypeInfo::types["array"]	= ARRAY;
	TypeInfo::types["function"] 	= FUNCTION;

	TypeInfo::types["vector2"]	= VECTOR2;
	TypeInfo::types["vector3"]	= VECTOR3;
	TypeInfo::types["vector4"] 	= VECTOR4;
	TypeInfo::types["quaternion"] 	= QUATERNION;
	TypeInfo::types["colour"]	= COLOUR;
	TypeInfo::types["degree"] 	= DEGREE;
	TypeInfo::types["radian"] 	= RADIAN;

	TypeInfo::types["rigidbody"] 	= RIGIDBODY;

	TypeInfo::init = true;
}

////////////////////////////////////////////////////////////////////////////////
//{{{ Value

/** Default constructor */
Value::Value(ValueType _type) throw()
{
	switch(_type)
		{
		case NIL:
			break;
		case BOOL:
			data.boolData = false;
			break;
		case INT:
			data.intData = 0;
			break;
		case FLOAT:
			data.floatData = 0;
			break;
		case STRING:
			data.cstrData = 0;
			break;
		default:
			assert(0);
			break;
		}
}

/** Copy constructor */
Value::Value(const Value &v) : type(v.type)
{
	switch(type)
	{
	case NIL:
	case INT:
	case BOOL:
	case FLOAT:
		data = v.data;
		break;
	case STRING:
		break;
	default:
		assert(0);
	}
}

Value::~Value() throw()
{
	switch(type)
		{
		//!TODO:
		default:
			break;
		}
}

bool Value::operator==(const Value& v)
{
	switch(type)
		{
		case NIL:
			return true;
			break;
		case BOOL:
			return data.boolData == v.data.boolData;
			break;
		case INT:
			return data.intData == v.data.intData;
			break;
		case FLOAT:
			return data.floatData == v.data.floatData;
			break;
		case STRING:
			return (data.cstrData == v.data.cstrData) || (strcmp(data.cstrData, v.data.cstrData)==0);
			break;
		default:
			assert(0);
			break;
		}
}

bool Value::operator!=(const Value& v)
{
	return !( *this == v );
}
//}}

void Value::swap( Value &other )
{
   ValueType temp = type;
   type = other.type;
   other.type = temp;
   std::swap( data, other.data );
}

#define VALUE_ASSIGN_OP(X) Value& Value::operator= (X v) \
{ \
	Value tmp(v); \
	swap(tmp); \
	return *this; \
}

VALUE_ASSIGN_OP(const Value&)
VALUE_ASSIGN_OP(bool)
VALUE_ASSIGN_OP(int)
VALUE_ASSIGN_OP(float)

